home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1997 #1 / Amiga Plus CD - 1997 - No. 01.iso / pd / programmierung / mesa-1.2.8 / widgets / demos / ed.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  17KB  |  655 lines

  1. /* ed.c -- Event Display (demo program for the MesaWS widget)
  2.    Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; see the file COPYING.  If not, write to
  16.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.    $Id: ed.c,v 1.16 1995/05/19 20:30:57 ohl Exp $
  19.  */
  20.  
  21. /* This is a simple event display as a demonstration of the MesaWS widget.
  22.    It reads a stream of simple event records from standard input (see the
  23.    file `events' for a example).
  24.  
  25.    It is a slow and crude hack.  */
  26.   
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <stdarg.h>
  30. #include <math.h>
  31. #ifndef M_PI
  32. #define M_PI 3.14159265358979323846
  33. #endif
  34. #include <X11/X.h>
  35. #include <X11/Intrinsic.h>
  36. #include <X11/StringDefs.h>
  37. #include <X11/Shell.h>
  38. #include <X11/Xaw/Box.h>
  39. #include <X11/Xaw/Command.h>
  40. #include <X11/Xaw/Form.h>
  41. #include <GL/xmesa.h>
  42. #include <GL/gl.h>
  43. #include <GL/glu.h>
  44. #include <GL/glx.h>
  45. #include <GL/MesaDrawingArea.h>
  46. #include <GL/MesaWorkstation.h>
  47.  
  48. static char *RCS_Id =
  49. "@(#) $Id: ed.c,v 1.16 1995/05/19 20:30:57 ohl Exp $";
  50.  
  51. static GLint Black, White, Red, Green, Blue, Yellow;
  52. Widget mesa, mesax, mesay, mesaz;
  53.  
  54. static void quit_function (Widget, XtPointer, XtPointer);
  55. static void next_function (Widget, XtPointer, XtPointer);
  56. static void next_event (void);
  57. static void update_angles (float, float);
  58. static void update_number (int);
  59.  
  60. static void
  61. Quit (Widget w, XEvent *event, String *argv, Cardinal *argc)
  62. {
  63.   quit_function (NULL, NULL, NULL);
  64. }
  65.  
  66. void
  67. Next (Widget w, XEvent *event, String *argv, Cardinal *argc)
  68. {
  69.   next_function (NULL, NULL, NULL);
  70. }
  71.  
  72. static XtActionsRec actions[] =
  73. {
  74.   {"Quit", Quit },
  75.   {"Next", Next },
  76. };
  77.  
  78. void
  79. quit_function (Widget w, XtPointer closure, XtPointer call_data)
  80. {
  81.   exit (0);
  82. }
  83.  
  84. void
  85. next_function (Widget w, XtPointer closure, XtPointer call_data)
  86. {
  87.   next_event ();
  88.   GLwRedrawObjects (mesa);
  89.   GLwRedrawObjects (mesax);
  90.   GLwRedrawObjects (mesay);
  91.   GLwRedrawObjects (mesaz);
  92. }
  93.  
  94. #define SET_POLAR(_p, _r, _theta, _phi) \
  95.     (_p)[0] = (_r) * sin (_theta) * cos (_phi), \
  96.     (_p)[1] = (_r) * sin (_theta) * sin (_phi), \
  97.     (_p)[2] = (_r) * cos (_theta)
  98. static void
  99. draw_barrel_segment (float bottom_radius, float top_radius,
  100.              float front_angle, float back_angle,
  101.              float half_angle)
  102. {
  103.   int i;
  104.   GLdouble top[4][3], bottom[4][3], *front[4], *back[4];
  105.  
  106.   SET_POLAR (top[0], top_radius, front_angle, half_angle);
  107.   SET_POLAR (top[1], top_radius, front_angle, -half_angle);
  108.   SET_POLAR (top[2], top_radius, back_angle, -half_angle);
  109.   SET_POLAR (top[3], top_radius, back_angle, half_angle);
  110.  
  111.   SET_POLAR (bottom[0], bottom_radius, front_angle, half_angle);
  112.   SET_POLAR (bottom[1], bottom_radius, front_angle, -half_angle);
  113.   SET_POLAR (bottom[2], bottom_radius, back_angle, -half_angle);
  114.   SET_POLAR (bottom[3], bottom_radius, back_angle, half_angle);
  115.  
  116.   front[0] = top[0];
  117.   front[1] = top[1];
  118.   front[2] = bottom[1];
  119.   front[3] = bottom[0];
  120.  
  121.   back[0] = top[3];
  122.   back[1] = top[2];
  123.   back[2] = bottom[2];
  124.   back[3] = bottom[3];
  125.  
  126.   glBegin (GL_LINE_LOOP);
  127.     for (i = 0; i <= 3; i++)
  128.       glVertex3dv (top[i]);
  129.   glEnd ();
  130.   
  131.   glBegin (GL_LINE_LOOP);
  132.     for (i = 0; i <= 3; i++)
  133.       glVertex3dv (bottom[i]);
  134.   glEnd ();
  135.   
  136.   glBegin (GL_LINE_LOOP);
  137.     for (i = 0; i <= 3; i++)
  138.       glVertex3dv (front[i]);
  139.   glEnd ();
  140.   
  141.   glBegin (GL_LINE_LOOP);
  142.     for (i = 0; i <= 3; i++)
  143.       glVertex3dv (back[i]);
  144.   glEnd ();
  145. }
  146.  
  147. static GLuint particles;
  148. static GLuint greek, latin, desc, desc_number, desc_angles;
  149.  
  150. static void
  151. next_event (void)
  152. {
  153.   char buffer[100];
  154.   enum
  155.     {
  156.       SKIP, READ, DONE
  157.     }
  158.   state;
  159.   int event = 0;
  160.   
  161.   glNewList (particles, GL_COMPILE);
  162.   glBegin (GL_LINES);
  163.   {
  164.     state = SKIP;
  165.     while (state != DONE)
  166.       {
  167.     int id;
  168.     float px, py, pz;
  169.     if (fgets (buffer, 100, stdin) == NULL)
  170.       state = DONE;
  171.     switch (state)
  172.       {
  173.       case SKIP:
  174.         if (sscanf (buffer, "BEGIN %d", &event) == 1)
  175.           state = READ;
  176.         break;
  177.       case READ:
  178.         if (sscanf (buffer, "%d %g %g %g",
  179.             &id, &px, &py, &pz) == 4)
  180.           {
  181.         if (id == 22)
  182.           {
  183.             /* Photons */
  184.             glIndexi (Red);
  185.             glColor3f (1.0, 0.0, 0.0);
  186.           }
  187.         else if ((11 == abs (id))
  188.              || (13 == abs (id))
  189.              || (15 == abs (id)))
  190.           {
  191.             /* Charged leptons */
  192.             glIndexi (Green);
  193.             glColor3f (0.0, 1.0, 0.0);
  194.           }
  195.         else if ((12 == abs (id))
  196.              || (14 == abs (id))
  197.              || (16 == abs (id)))
  198.           {
  199.             /* Neutral leptons */
  200.             glIndexi (Yellow);
  201.             glColor3f (1.0, 1.0, 0.0);
  202.           }
  203.         else if ((abs (id) <= 6) || (100 <= abs (id)))
  204.           {
  205.             /* Quarks/Hadrons */
  206.             glIndexi (Blue);
  207.             glColor3f (0.0, 0.0, 1.0);
  208.           }
  209.         else
  210.           {
  211.             /* ??? */
  212.             glIndexi (White);
  213.             glColor3f (1.0, 1.0, 1.0);
  214.           }
  215.         glVertex3f (0.0, 0.0, 0.0);
  216.         glVertex3f (px, py, pz);
  217.           }
  218.         else if (strncmp ("END", buffer, 3) == 0)
  219.           state = DONE;
  220.         break;
  221.       case DONE:
  222.         /* never happens */
  223.         break;
  224.       }
  225.       }
  226.   }
  227.   glEnd ();
  228.   glEndList ();
  229.  
  230.   update_number (event);
  231. }
  232.  
  233. static void
  234. update_angles (float theta, float phi)
  235. {
  236.   char msg[64];
  237.   sprintf (msg, "f=%5.2fp, q=%5.2fp", phi/M_PI, theta/M_PI);
  238.   glNewList (desc_angles, GL_COMPILE);
  239.     glCallLists (strlen (msg), GL_BYTE, msg);
  240.   glEndList ();
  241. }  
  242.  
  243. static void
  244. update_number (int event)
  245. {
  246.   char msg[32];
  247.   sprintf (msg, "ADLO/TH, #%d", event);
  248.   glNewList (desc_number, GL_COMPILE);
  249.     glCallLists (strlen (msg), GL_BYTE, msg);
  250.   glEndList ();
  251. }  
  252.  
  253. static void
  254. setup_context (Widget w)
  255. {
  256.   GLwMakeCurrent (w);
  257.   glClearColor (0.0, 0.0, 0.0, 0.0);
  258.   glClearIndex (Black);
  259.   glShadeModel (GL_FLAT);
  260. }
  261.  
  262. static GLint
  263. alloc_color (Widget w, Colormap cmap, int red, int green, int blue)
  264.   XColor xcolor;
  265.   xcolor.red = red;
  266.   xcolor.green = green;
  267.   xcolor.blue = blue;
  268.   xcolor.flags = DoRed | DoGreen | DoBlue;
  269.   if (!XAllocColor (XtDisplay (w), cmap, &xcolor))
  270.     {
  271.       printf ("Couldn't allocate color!\n");
  272.       exit (1);
  273.     }
  274.   return xcolor.pixel;
  275. }
  276.  
  277. /* This is rather inefficient, but we don't mind for the moment,
  278.    because it works.  */
  279.  
  280. static void
  281. translate_pixels (Widget to, Widget from, ...)
  282. {
  283.   va_list ap;
  284.   char *name;
  285.   Colormap from_cmap, to_cmap;
  286.   XColor xcolor;
  287.  
  288.   XtVaGetValues (from, XtNcolormap, &from_cmap, NULL);
  289.   XtVaGetValues (to, XtNcolormap, &to_cmap, NULL);
  290.  
  291.   va_start (ap, from);
  292.   for (name = va_arg (ap, char *); name != NULL; name = va_arg (ap, char *))
  293.     {
  294.       XtVaGetValues (from, name, &xcolor.pixel, NULL);
  295.       XQueryColor (XtDisplay (from), from_cmap, &xcolor);
  296.       if (!XAllocColor (XtDisplay (to), to_cmap, &xcolor))
  297.     XtAppWarning (XtWidgetToApplicationContext (to),
  298.               "Couldn't allocate color!\n");
  299.       else
  300.     XtVaSetValues (from, name, xcolor.pixel, NULL);
  301.     }
  302.   va_end (ap);
  303. }
  304.  
  305. static Widget
  306. create_label (Widget parent, char *name, char *text)
  307. {
  308.   return XtVaCreateManagedWidget (name, labelWidgetClass, parent,
  309.                   XtNlabel, text, NULL);
  310. }
  311.  
  312. static Widget
  313. create_ok (Widget parent, char *name, XtCallbackProc cb)
  314. {
  315.   Widget ok;
  316.   ok = XtVaCreateManagedWidget (name, commandWidgetClass, parent,
  317.                   XtNlabel, "OK", NULL);
  318.   XtAddCallback (ok, XtNcallback, cb, NULL);
  319.   return ok;
  320. }
  321.  
  322. static Widget
  323. create_command (Widget parent, char *name, XtCallbackProc cb)
  324. {
  325.   Widget ok;
  326.   ok = XtVaCreateManagedWidget (name, commandWidgetClass, parent, NULL);
  327.   XtAddCallback (ok, XtNcallback, cb, NULL);
  328.   return ok;
  329. }
  330.  
  331. static Widget
  332. create_popup (Widget parent, char *name)
  333. {
  334.   return XtVaCreatePopupShell (name, transientShellWidgetClass, parent, NULL);
  335. }
  336.  
  337. static Widget
  338. create_box (Widget parent, char *name)
  339. {
  340.   return XtVaCreateManagedWidget (name, boxWidgetClass, parent,
  341.                   XtNorientation, XtorientVertical, NULL);
  342. }
  343.  
  344.    
  345. Widget about_shell, help_shell;
  346.  
  347. char about_message[] = "\
  348. This is ed, a simple particle physics event display\n\
  349. application and demo for the MesaWorkstation widget.\n\
  350. \n\
  351. Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de\n\
  352. \n\
  353. This is free software; see the source for copying conditions.\n\
  354. There is NO warranty; not even for MERCHANTABILITY\n\
  355. or FITNESS FOR A PARTICULAR PURPOSE.";
  356.  
  357. void
  358. popup_about (Widget w, XtPointer closure, XtPointer call_data)
  359. {
  360.   XtPopup (about_shell, XtGrabNonexclusive);
  361. }
  362.  
  363. void
  364. popdown_about (Widget w, XtPointer closure, XtPointer call_data)
  365. {
  366.   XtPopdown (about_shell);
  367. }
  368.  
  369.  
  370. char help_message[] = "\
  371. Sorry, no online help available yet.\n\
  372. \n\
  373. See the manpage or the source of the MesaWorkstation widget\n\
  374. for the available keystroke translations and their actions.\n\
  375. For a start, use the cursor keys to rotate the object.\n\
  376. \n\
  377. The color code of the particles is as follows:\n\
  378. \n\
  379.   red:    photons\n\
  380.   green:  charged leptons (electrons, muons, taus)\n\
  381.   yellow: neutrinos\n\
  382.   blue:   hadrons (incl. quarks)\n\
  383.   while:  unidentified\n";
  384.  
  385. void
  386. popup_help (Widget w, XtPointer closure, XtPointer call_data)
  387. {
  388.   XtPopup (help_shell, XtGrabNonexclusive);
  389. }
  390.  
  391. void
  392. popdown_help (Widget w, XtPointer closure, XtPointer call_data)
  393. {
  394.   XtPopdown (help_shell);
  395. }
  396.  
  397.  
  398. static XrmOptionDescRec options[] =
  399. {
  400.   { "-debug", "*debug", XrmoptionNoArg, "True" },
  401.   { "-rgba", "*rgba", XrmoptionNoArg, "True" },
  402.   { "-doublebuffer", "*doublebuffer", XrmoptionNoArg, "True" },
  403.   { "-ximage", "*ximage", XrmoptionNoArg, "True" },
  404. };
  405.  
  406. static String fallback_resources[] =
  407. {
  408.   "*MesaWorkstation.debug: false",
  409.   "*MesaWorkstation.rgba: false",
  410.   "*MesaWorkstation.installColormap: true",
  411.   "*MesaWorkstation.doublebuffer: true",
  412.   "*MesaWorkstation.ximage: false",
  413.   "*MesaWorkstation.translations: #augment \
  414.    <Key>q: Quit()\n\
  415.    <Key>Return: Next()\n\
  416.    <Key>space: Next()",
  417.   "*help.label: Help",
  418.   "*about.label: About ed",
  419.   "*quit.label: Exit",
  420.   "*next.label: Next event",
  421.   "*mesa.width: 400",
  422.   "*mesa.height: 400",
  423.   "*mesax.width: 100",
  424.   "*mesax.height: 100",
  425.   "*mesay.width: 100",
  426.   "*mesay.height: 100",
  427.   "*mesaz.width: 100",
  428.   "*mesaz.height: 100",
  429.   NULL
  430. };
  431.  
  432. int
  433. main (int argc, char *argv[])
  434. {
  435.   Widget top, frame, commands, next, quit;
  436.   Widget about, about_box, about_text, about_id, about_ok;
  437.   Widget help, help_box, help_text, help_ok;
  438.   XtAppContext app_context;
  439.   Boolean rgba, cmap_installed;
  440.   
  441.   GLuint barrel, object;
  442.  
  443.   top = XtVaAppInitialize (&app_context, "Ed",
  444.                options, XtNumber (options),
  445.                &argc, argv, fallback_resources,
  446.                NULL);
  447.  
  448.   frame = XtVaCreateManagedWidget ("frame", formWidgetClass,
  449.                    top,
  450.                    NULL);
  451.  
  452.   commands = XtVaCreateManagedWidget ("commands", boxWidgetClass,
  453.                       frame,
  454.                       XtNhSpace, 10,
  455.                       XtNorientation, XtorientHorizontal,
  456.                       NULL);
  457.  
  458.   help = create_command (commands, "help", popup_help);
  459.   help_shell = create_popup (top, "help_shell");
  460.   help_box = create_box (help_shell, "help_box");
  461.   help_text = create_label (help_box, "help_text", help_message);
  462.   help_ok = create_ok (help_box, "help_ok", popdown_help);
  463.  
  464.   about = create_command (commands, "about", popup_about);
  465.   about_shell = create_popup (top, "about_shell");
  466.   about_box = create_box (about_shell, "about_box");
  467.   about_text = create_label (about_box, "about_text", about_message);
  468.   about_id = create_label (about_box, "about_id", RCS_Id);
  469.   about_ok = create_ok (about_box, "about_ok", popdown_about);
  470.  
  471.   next = create_command (commands, "next", next_function);
  472.   quit = create_command (commands, "quit", quit_function);
  473.  
  474.   mesa = XtVaCreateManagedWidget ("mesa", mesaWorkstationWidgetClass,
  475.                   frame,
  476.                   GLwNshareLists, True,
  477.                   XtNfromVert, commands, XtNvertDistance, 10,
  478.                   NULL);
  479.  
  480.   mesax = XtVaCreateManagedWidget ("mesax", mesaWorkstationWidgetClass,
  481.                    frame,
  482.                    GLwNshareLists, True,
  483.                    XtNfromVert, mesa, XtNvertDistance, 10,
  484.                    NULL);
  485.   mesay = XtVaCreateManagedWidget ("mesay", mesaWorkstationWidgetClass,
  486.                    frame,
  487.                    GLwNshareLists, True,
  488.                    XtNfromVert, mesa, XtNvertDistance, 10,
  489.                    XtNfromHoriz, mesax, XtNhorizDistance, 50,
  490.                    NULL);
  491.   mesaz = XtVaCreateManagedWidget ("mesaz", mesaWorkstationWidgetClass,
  492.                    frame,
  493.                    GLwNshareLists, True,
  494.                    XtNfromVert, mesa, XtNvertDistance, 10,
  495.                    XtNfromHoriz, mesay, XtNhorizDistance, 50,
  496.                    NULL);
  497.  
  498.   XtAppAddActions (app_context, actions, XtNumber (actions));
  499.   
  500.   XtRealizeWidget (top);
  501.  
  502.   XtVaGetValues (mesa,
  503.          GLwNrgba, &rgba,
  504.          GLwNinstallColormap, &cmap_installed,
  505.          NULL);
  506.   if (rgba)
  507.     {
  508.       Black = White = Red = Green = Blue = Yellow = 0;
  509.  
  510.       if (cmap_installed)
  511.     {
  512.       /* In RGBA mode, the Mesa widgets will have their own color map.
  513.          Adjust the colors of the other widgets so that--even if the rest
  514.          of the screen has wrong colors--all application widgets have the
  515.          right colors.  */
  516.              
  517.       translate_pixels (mesa, quit,
  518.                 XtNbackground, XtNforeground, XtNborder, NULL);
  519.       translate_pixels (mesa, next,
  520.                 XtNbackground, XtNforeground, XtNborder, NULL);
  521.       translate_pixels (mesa, help,
  522.                 XtNbackground, XtNforeground, XtNborder, NULL);
  523.       translate_pixels (mesa, about,
  524.                 XtNbackground, XtNforeground, XtNborder, NULL);
  525.       translate_pixels (mesa, commands, XtNbackground, XtNborder, NULL);
  526.       translate_pixels (mesa, frame, XtNbackground, XtNborder, NULL);
  527.       
  528.       /* Finally warp the pointer into the mesa widget, to make sure that
  529.          the user sees the right colors at the beginning.  */
  530.  
  531.       XWarpPointer (XtDisplay (mesa), None, XtWindow (mesa), 0, 0, 0, 0, 0, 0);
  532.     }
  533.     }
  534.   else
  535.     {
  536.       /* Allocate a few colors for use in color index mode.  */
  537.  
  538.       Colormap cmap;
  539.       cmap = DefaultColormap (XtDisplay (top), DefaultScreen (XtDisplay (top)));
  540.       Black  = alloc_color (top, cmap, 0x0000, 0x0000, 0x0000);
  541.       White  = alloc_color (top, cmap, 0xffff, 0xffff, 0xffff);
  542.       Red    = alloc_color (top, cmap, 0xffff, 0x0000, 0x0000);
  543.       Green  = alloc_color (top, cmap, 0x0000, 0xffff, 0x0000);
  544.       Blue   = alloc_color (top, cmap, 0x0000, 0x0000, 0xffff);
  545.       Yellow = alloc_color (top, cmap, 0xffff, 0xffff, 0x0000);
  546.     }
  547.  
  548.   setup_context (mesa);
  549.   setup_context (mesax);
  550.   setup_context (mesay);
  551.   setup_context (mesaz);
  552.  
  553.   GLwSetFrustumProjection (mesa, -1.0, 1.0, -1.0, 1.0, 1.0, 10.0);
  554.   GLwSetPolarView (mesa, 3, M_PI/2, 0.0);
  555.  
  556.   GLwBeginProjection (mesax);
  557.   glOrtho (-1.5, 1.5, -1.5, 1.5, 1.0, 10.0);
  558.   GLwEndProjection ();
  559.   GLwPostProjection (mesay, GLwGetProjectionList (mesax));
  560.   GLwPostProjection (mesaz, GLwGetProjectionList (mesax));
  561.  
  562.   GLwBeginView (mesax);
  563.   gluLookAt (3.0, 0.0, 0.0,  0.0, 0.0, 0.0,  0.0, 1.0, 0.0);
  564.   GLwEndView ();
  565.  
  566.   GLwBeginView (mesay);
  567.   gluLookAt (0.0, 3.0, 0.0,  0.0, 0.0, 0.0,  0.0, 0.0,-1.0);
  568.   GLwEndView ();
  569.  
  570.   GLwBeginView (mesaz);
  571.   gluLookAt (0.0, 0.0, 3.0,  0.0, 0.0, 0.0,  0.0, 1.0, 0.0);
  572.   GLwEndView ();
  573.  
  574.   barrel = glGenLists (1);
  575.   glNewList (barrel, GL_COMPILE);
  576.   {
  577.     draw_barrel_segment (0.9, 1.0,
  578.              0.3 * M_PI, 0.7 * M_PI,
  579.              0.1 * M_PI);
  580.   }
  581.   glEndList ();
  582.  
  583.   particles = glGenLists (1);
  584.   glNewList (particles, GL_COMPILE);
  585.   glEndList ();
  586.  
  587.   object = glGenLists (1);
  588.   glNewList (object, GL_COMPILE);
  589.   {
  590.     float frac;
  591.     glClear (GL_COLOR_BUFFER_BIT);
  592.     glIndexi (White);
  593.     glColor3f (1.0, 1.0, 1.0);
  594.     for (frac = 0; frac < 1.0; frac += 0.125)
  595.       {
  596.     glPushMatrix ();
  597.       glRotatef (frac * 360, 0.0, 0.0, 1.0);
  598.       glCallList (barrel);
  599.     glPopMatrix ();
  600.       }
  601.     glPushMatrix ();
  602.       glCallList (particles);
  603.     glPopMatrix ();
  604.   }
  605.   glEndList ();
  606.  
  607. #if 0
  608.   greek = glGenLists (128);
  609.   glXUseXFont (XLoadFont (XtDisplay (top), "*-symbol-*-240-*"),
  610.            0, 128, greek);
  611. #endif
  612.   latin = glGenLists (128);
  613.   glXUseXFont (XLoadFont (XtDisplay (top), "*-times-*-240-*"),
  614.            0, 128, latin);
  615.  
  616.   desc_number = glGenLists (1);
  617.   update_number (0);
  618.   desc_angles = glGenLists (1);
  619.   update_angles (0.0, 0.0);
  620.  
  621.   desc = glGenLists (1);
  622.   glNewList (desc, GL_COMPILE);
  623.   {
  624.     glMatrixMode (GL_PROJECTION);
  625.     glLoadIdentity ();
  626.     glOrtho (0, 400, 0, 400, -1.0, 1.0);
  627.     glMatrixMode (GL_MODELVIEW);
  628.     glLoadIdentity ();
  629.     glIndexi (White);
  630.     glColor3f (1.0, 1.0, 1.0);
  631.     glPushAttrib (GL_LIST_BIT);
  632.       glRasterPos2i (10.0, 10.0);
  633.       glListBase (latin);
  634.       glCallList (desc_number);
  635. #if 0
  636.       glRasterPos2i (10.0, 380.0);
  637.       glListBase (greek);
  638.       glCallList (desc_angles);
  639. #endif
  640.     glPopAttrib ();
  641.   }
  642.   glEndList ();
  643.   
  644.   GLwPostObject (mesa, object);
  645.   GLwPostObject (mesax, object);
  646.   GLwPostObject (mesay, object);
  647.   GLwPostObject (mesaz, object);
  648.   GLwPostObject (mesa, desc);
  649.  
  650.   XtAppMainLoop (app_context);
  651.   return (0);
  652. }
  653.  
  654.